import 'dart:async';
import 'package:just_audio/just_audio.dart';

typedef PlayStateListener = void Function(PlayerState playState);
typedef SoundInterruptListener = void Function();

/// 类 `SoundPlayer`，是一个用于播放音频的工具类，用于在 Flutter 应用程序中进行音频播放操作。
///
/// 该类具有以下功能和作用：
///
/// 1. 创建单例对象：通过工厂构造函数创建一个单例对象，确保在应用程序中只有一个 `SoundPlayer` 实例。
/// 2. 音频播放器：使用 `just_audio` 库提供的 `AudioPlayer` 类作为音频播放器。
/// 3. 播放网络音频：通过 `playUrl` 方法播放网络音频。该方法会停止当前正在播放的音频，并设置音频播放器的 URL 为指定的网络音频地址，然后开始播放。
/// 4. 播放本地音频：通过 `playLocal` 方法播放本地音频。该方法会停止当前正在播放的音频，并设置音频播放器的文件路径为指定的本地音频文件路径，然后开始播放。
/// 5. 是否正在播放：通过 `isPlaying` 属性获取当前音频播放器是否正在播放音频的状态。
/// 6. 停止播放：通过 `stop` 方法停止当前正在播放的音频。如果音频播放器正在播放音频，将停止播放。
/// 7. 释放资源：通过 `dispose` 方法释放音频播放器的资源。在不需要音频播放功能时，可以调用该方法进行资源释放，以避免资源泄漏。
/// 8. 监听播放状态：通过 `playStateListener` 方法监听音频播放状态的变化。可以传入一个回调函数作为参数，当播放状态发生变化时，将通过回调函数返回 `PlayerState` 对象，可以根据具体的播放状态进行相应的处理。
class SoundPlayer {
  // 单例
  static final SoundPlayer _instance = SoundPlayer._internal();

  // 音频播放器
  static SoundInterruptListener? _soundInterruptListener;

  // 音频播放器
  final AudioPlayer _audioPlayer = AudioPlayer();

  // 当前正在播放的消息 ID
  String currentPlayedMsgId = "";

  // 工厂构造函数
  factory SoundPlayer() {
    return _instance;
  }

  // 私有构造函数
  SoundPlayer._internal();

  // 播放网路音频
  Future<void> playUrl({required String url}) async {
    stop();
    if (_soundInterruptListener != null) {
      _soundInterruptListener!();
    }
    await _audioPlayer.setUrl(url);
    await _audioPlayer.play();
  }

  // 播放本地音频
  Future<void> playLocal({required String localFile}) async {
    stop();
    if (_soundInterruptListener != null) {
      _soundInterruptListener!();
    }
    await _audioPlayer.setFilePath(localFile);
    await _audioPlayer.play();
  }

  // 是否正在播放
  bool get isPlaying => _audioPlayer.playing;

  // 停止播放
  void stop() {
    currentPlayedMsgId = '';
    if (_audioPlayer.playing) {
      _audioPlayer.stop();
    }
  }

  // 释放资源
  void dispose() {
    _audioPlayer.dispose();
  }

  // 监听播放状态
  StreamSubscription<PlayerState> playStateListener(
          void Function(PlayerState)? listener) =>
      _audioPlayer.playerStateStream.listen(listener);
}
